import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Between, Like, Repository } from 'typeorm';
import { OperationRecord } from './entities/operation-record.entity';
import { CreateOperationRecordDto, GetOperationRecordPageDto } from './dto/operation-record.dto';
import { isArray } from 'src/utlis/tools';
import { getPagination, throwHttp } from 'src/utlis';
import { isNil } from 'ramda';
import { getMetadataArgsStorage } from 'typeorm';

@Injectable()
export class OperationRecordService {
    constructor(
        @InjectRepository(OperationRecord)
        private operationRecordRepository: Repository<OperationRecord>,
    ) { }
    /** 操作记录 */
    async getOperationRecordPage(params: GetOperationRecordPageDto) {
        try {
            const { createTimeStart, createTimeEnd, } = params;
            const { pageSize, pageNum } = getPagination({
                pageSize: params.pageSize,
                pageNum: params.pageNum,
            });
            const where: GetOperationRecordPageDto = {
                name: Like(`%${params.name || ''}%`),
                operateType: params.operateType,
                method: params.method,
                userId: params.userId,
                ip: params.ip,
                interfacePath: params.interfacePath,
            };
            // 时间筛选
            if (!isNil(createTimeStart) && !isNil(createTimeEnd)) {
                where.createDate = Between(createTimeStart, createTimeEnd);
            }
            // 过滤掉为 `undefined` 的属性
            Object.keys(where).forEach(key => where[key] === undefined && delete where[key]);
            const [records, total] = await this.operationRecordRepository.findAndCount({
                where,
                relations: ['user'],
                select: {
                    user: {
                        username: true,
                    },
                },
                order: { createDate: 'DESC' },
                skip: pageNum * pageSize,
                take: pageSize,
                cache: true,
            });
            // 手动将 username 提升到第一层
            const data = records.map((record) => ({
                ...record,
                username: record.user?.username || null,
            }));
            return {
                data,
                total,
                pageSize,
                pageNum: pageNum + 1,
            };
        } catch (error) {
            throwHttp(error.message);
        }
    }
    async createOperationRecord(body: CreateOperationRecordDto, userId: number) {
        const record = new OperationRecord();
        record.userId = userId;
        record.operation = body.operation;
        record.name = body.name;
        record.ip = body.ip;
        record.method = body.method;
        record.operateType = body.operateType;
        record.outside = body.outside;
        record.dataId = body.dataId;
        record.interfacePath = body.interfacePath;
        await this.operationRecordRepository.save(record);
    }
    convertToChinese(records: any[], entity: any) {
        const type = this.getAllFieldNames(entity);
        return records.map(record => {
            let name = type[record.name]
            if (record.type === 'delete-array') {
                return `删除${name}：${JSON.stringify(record.lhs)} => ${JSON.stringify(record.rhs)}`
            } else if (record.type === 'add-array') {
                return `添加${name}：${JSON.stringify(record.lhs)} => ${JSON.stringify(record.rhs)}`
            }
            return `${name}：${record.lhs} => ${record.rhs}`
        }).join('\n');
    }
    /** 获取 AdminUser 所有字段的中文名称 */
    getAllFieldNames(entity: any): Record<string, string> {
        const metadata = getMetadataArgsStorage();
        const columns = metadata.columns.filter(col => col.target === entity);
        const result: Record<string, string> = {};
        columns.forEach((column) => {
            const name = column.options.comment || column.propertyName;
            if (name) {
                result[column.propertyName] = name;
            }
        });
        return result;
    }
}